home *** CD-ROM | disk | FTP | other *** search
- /* intercepts.c: This file is currently the only source file for
- the logwrites filter library.
-
- Written by Adam J. Richter
- Copyright 1996 Yggdrasil Computing, Inc.
-
- Logwrites and its documentation, including this file, may be freely
- copied under the terms and conditions of version 2 of the GNU General
- Public License, as published by the Free Software Foundation
- (Cambridge, Massachusetts, United States of America).
-
- */
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/param.h>
- #include <fcntl.h>
- #include <stdarg.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <syscall.h>
- #include <stdio.h>
-
- static int initialized = 0;
- static int recursive = 0;
-
- #define PREFIX "write "
-
- static char cwd[MAXPATHLEN + 1] = PREFIX;
- static char *install_log = NULL;
- static char *do_backups = NULL;
-
- static void
- initialize (void) {
- int len;
-
- if (initialized) return;
-
- if (getcwd(cwd,sizeof(cwd)) == NULL) {
- strcpy (cwd, "?");
- /* fail silently */
- }
- install_log = getenv ("INSTALL_LOG");
- do_backups = getenv ("DO_BACKUPS");
- initialized = 1;
- }
-
- static void
- log_event( char *format, ... ) {
- va_list arg_ptr;
- FILE *log_file;
-
- if (!initialized) initialize();
- if (recursive || !install_log) return;
- recursive = 1;
- if ((log_file = fopen (install_log, "a")) == NULL) {
- recursive = 0;
- return;
- }
-
- va_start(arg_ptr,format);
- vfprintf (log_file, format, arg_ptr);
- va_end(arg_ptr);
-
- fclose(log_file);
- recursive = 0;
- }
-
- static int
- gen_backup_filename (const char *filename, char *backup_filename /* OUT */) {
- struct stat statbuf;
- int i;
- char *ptr;
- sprintf (backup_filename, "%s.old", filename);
- if (lstat (backup_filename, &statbuf) < 0) return;
- ptr = backup_filename + strlen(backup_filename);
- *(ptr++) = '.';
- for (i = 1;i != 0;i++) {
- sprintf (ptr, "%d", i);
- if (lstat (backup_filename, &statbuf) < 0) return 1;
- }
- backup_filename[0] = '\0';
- return 0;
- }
-
-
- static int
- backup_file (const char *filename, char *backup_filename,
- int regular_file_only) {
- struct stat statbuf;
-
- if (!initialized) initialize();
- if (!do_backups) return 0;
- if (recursive) return 0;
- if (lstat (filename, &statbuf) >= 0 &&
- (S_ISREG(statbuf.st_mode) || !regular_file_only) &&
- gen_backup_filename(filename, backup_filename)) {
- syscall(SYS_rename, filename, backup_filename);
- return 1;
- }
- return 0;
- }
-
-
- int
- link (const char *oldpath, const char *newpath) {
- int result;
-
- if ((result = syscall(SYS_link, oldpath, newpath)) >= 0) {
- log_event("link %s %s %s\n", cwd, oldpath, newpath);
- }
- return result;
- }
-
- int
- rename (const char *oldpath, const char *newpath) {
- int result;
- int backed_up;
- char backup_filename[MAXPATHLEN+1];
-
- backed_up = backup_file(newpath, backup_filename, 0);
- if ((result = syscall(SYS_rename, oldpath, newpath)) >= 0) {
- if (backed_up) {
- log_event("backup %s %s %s\n", cwd, newpath, backup_filename);
- }
- log_event("rename %s %s %s\n", cwd, oldpath, newpath);
- } else {
- if (backed_up) {
- syscall(SYS_rename, backup_filename, newpath);
- }
- }
- return result;
- }
-
- int
- symlink (const char *oldpath, const char *newpath) {
- int result;
-
- if ((result = syscall(SYS_symlink, oldpath, newpath)) >= 0) {
- log_event("symlink %s %s %s\n", cwd, oldpath, newpath);
- }
- return result;
- }
-
- int
- unlink (const char *filename) {
- int result;
- char backup_filename[MAXPATHLEN+1];
- int backed_up;
-
- backed_up = backup_file(filename, backup_filename, 0);
- if ((result = syscall(SYS_unlink, filename)) >= 0) {
- if (backed_up) {
- log_event("backup %s %s %s\n", cwd, filename, backup_filename);
- }
- log_event("unlink %s %s\n", cwd, filename);
- } else {
- if (backed_up) {
- syscall(SYS_rename, backup_filename, filename);
- }
- }
- return result;
- }
-
- int
- truncate (const char *filename, size_t length) {
- int result;
- char backup_filename[MAXPATHLEN+1];
- int backed_up;
-
- if (length == 0) {
- backed_up = backup_file(filename, backup_filename, 0);
- } else {
- backed_up = 0;
- }
- if ((result = syscall(SYS_unlink, filename)) >= 0) {
- if (backed_up) {
- log_event("backup %s %s %s\n", cwd, filename, backup_filename);
- }
- if (length == 0) {
- log_event("truncate %s %s %d\n", cwd, filename, length);
- }
- } else {
- if (backed_up) {
- syscall(SYS_rename, backup_filename, filename);
- }
- }
- return result;
- }
-
- int
- prev_mknod (const char *filename, mode_t mode, dev_t dev) {
- int result;
-
- if ((result = syscall(SYS_prev_mknod, mode, dev)) >= 0) {
- log_event("mknod %s %s 0%o 0x%x\n", cwd, filename, mode, dev);
- }
- return result;
- }
-
- int
- mkdir (const char *pathname, mode_t mode) {
- int result;
-
- if ((result = syscall(SYS_mkdir, pathname, mode)) >= 0) {
- log_event("mkdir %s %s 0%o\n", cwd, pathname, mode);
- }
- return result;
- }
-
- /* XXX: Also intercept rmdir? */
-
- int
- open( const char *filename, int flags, ... ) {
- int result;
- mode_t mode;
- va_list arg_ptr;
- char backup_filename[MAXPATHLEN+1];
- int backed_up;
- int record_event;
-
- va_start(arg_ptr,flags);
- mode = va_arg(arg_ptr, mode_t);
- va_end(arg_ptr);
-
- /* Only log write-only opens that will create the file if it doesn't
- exist. Otherwise, it is probably not an installation. */
- if ((flags & O_ACCMODE) == O_WRONLY && (flags & O_CREAT) &&
- (flags & O_TRUNC)) {
-
- backed_up = backup_file(filename, backup_filename, 1);
- record_event = 1;
- } else {
- backed_up = 0;
- record_event = 0;
- }
-
- result = syscall(SYS_open, filename, flags, mode);
-
- if (backed_up) {
- if (result < 0) {
- syscall(SYS_rename, backup_filename, filename);
- } else {
- log_event("backup %s %s %s\n", cwd, filename, backup_filename);
- }
- }
- if (record_event) {
- log_event("write %s %s 0x%x 0%o\n", cwd, filename, flags, mode);
- }
- return result;
- }
-